home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / screen3 / part04 < prev    next >
Encoding:
Text File  |  1991-12-19  |  53.4 KB  |  2,219 lines

  1. Newsgroups: comp.sources.unix
  2. From: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  3. Subject: v25i044: Screen3 - multiple windows on an ASCII terminal, Part04/08
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  8. Posting-Number: Volume 25, Issue 44
  9. Archive-Name: screen3/part04
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 4 (of 8)."
  18. # Contents:  mark.c socket.c
  19. # Wrapped by vixie@cognition.pa.dec.com on Thu Dec 19 17:36:05 1991
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'mark.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'mark.c'\"
  23. else
  24. echo shar: Extracting \"'mark.c'\" \(25040 characters\)
  25. sed "s/^X//" >'mark.c' <<'END_OF_FILE'
  26. X/* Copyright (c) 1991
  27. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  28. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  29. X * Copyright (c) 1987 Oliver Laumann
  30. X *
  31. X * This program is free software; you can redistribute it and/or modify
  32. X * it under the terms of the GNU General Public License as published by
  33. X * the Free Software Foundation; either version 1, or (at your option)
  34. X * any later version.
  35. X *
  36. X * This program is distributed in the hope that it will be useful,
  37. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  38. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39. X * GNU General Public License for more details.
  40. X *
  41. X * You should have received a copy of the GNU General Public License
  42. X * along with this program (see the file COPYING); if not, write to the
  43. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  44. X *
  45. X * Noteworthy contributors to screen's design and implementation:
  46. X *    Wayne Davison (davison@borland.com)
  47. X *    Patrick Wolfe (pat@kai.com, kailand!pat)
  48. X *    Bart Schaefer (schaefer@cse.ogi.edu)
  49. X *    Nathan Glasser (nathan@brokaw.lcs.mit.edu)
  50. X *    Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
  51. X *    Howard Chu (hyc@hanauma.jpl.nasa.gov)
  52. X *    Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
  53. X *    Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
  54. X *    Marc Boucher (marc@CAM.ORG)
  55. X *
  56. X ****************************************************************
  57. X */
  58. X
  59. X#ifndef lint
  60. X  static char rcs_id[] = "$Id: mark.c,v 1.38 91/10/11 11:46:04 jnweiger Exp $ FAU";
  61. X#endif
  62. X
  63. X#include <sys/types.h>
  64. X#if defined(BSD) || defined(sequent)
  65. X# include <strings.h>
  66. X#else
  67. X# include <string.h>
  68. X#endif
  69. X
  70. X#include "config.h"
  71. X#include "screen.h"
  72. X#include "ansi.h"    /* here we find A_SO, ASCII, EXPENSIVE */
  73. X#include "extern.h"
  74. X
  75. static int is_letter __P((int));
  76. static void nextword __P((int *, int *, int, int));
  77. static int linestart __P((int));
  78. static int lineend __P((int));
  79. static int rem __P((int, int , int , int , int , char *, int));
  80. static int eq __P((int, int ));
  81. static void revto __P((int, int));
  82. static void revto_line __P((int, int, int));
  83. static void MarkRedisplayLine __P((int, int, int, int));
  84. static int MarkRewrite __P((int, int, int, int));
  85. static void process_mark_input __P((char **, int *));
  86. static void AbortMarkRoutine __P((void));
  87. static int MarkScrollDownDisplay __P((int));
  88. static int MarkScrollUpDisplay __P((int));
  89. X
  90. int join_with_cr =  0;
  91. extern struct win *fore, *wtab[];
  92. extern int screenwidth, screenheight;
  93. extern int screentop, screenbot;
  94. extern char GlobalAttr, GlobalCharset;
  95. extern int in_ovl;
  96. extern int HS;
  97. extern int LP;
  98. extern char *null, *blank;
  99. X
  100. X#ifdef NETHACK
  101. extern nethackflag;
  102. X#endif
  103. X
  104. char *copybuffer = NULL;
  105. int copylen = 0;
  106. char mark_key_tab[256]; /* this array must be initialised first! */
  107. X
  108. static int in_mark;    /* mark routine active */
  109. static int left_mar, right_mar, nonl;
  110. static int x1, y1, second; /* y1 is in terms of WIN coordinates, not DISPLAY */
  111. static int cx, cy;    /* Cursor Position in WIN coords*/
  112. static rep_cnt;        /* no. of repeats are rep_cnt+1. jw. */
  113. static int append_mode;    /* shall we overwrite or append to copybuffer */
  114. static write_buffer;    /* shall we do a KEY_WRITE_EXCHANGE right away? */
  115. static hist_offset;
  116. X
  117. static int is_letter(c)
  118. char c;
  119. X{
  120. X  if (c >= 'a' && c <= 'z' ||
  121. X      c >= 'A' && c <= 'Z' ||
  122. X      c >= '0' && c <= '9' ||
  123. X      c == '_' || c == '.' ||
  124. X      c == '@' || c == ':' ||
  125. X      c == '%' || c == '!' ||
  126. X      c == '-' || c == '+')
  127. X    /* thus we can catch email-addresses as a word :-) */
  128. X    return 1;
  129. X  else if (c != ' ')
  130. X    return 2;
  131. X  return 0;
  132. X}
  133. X
  134. X/*
  135. X * iWIN gives us a reference to line y of the *whole* image 
  136. X * where line 0 is the oldest line in our history.
  137. X * y must be in WIN coordinate system, not in display.
  138. X */
  139. X#define iWIN(y) ((y < fore->histheight) ? fore->ihist[(fore->histidx + y)\
  140. X        % fore->histheight] : fore->image[y - fore->histheight])
  141. X#define aWIN(y) ((y < fore->histheight) ? fore->ahist[(fore->histidx + y)\
  142. X        % fore->histheight] : fore->attr[y - fore->histheight])
  143. X#define fWIN(y) ((y < fore->histheight) ? fore->fhist[(fore->histidx + y)\
  144. X        % fore->histheight] : fore->font[y - fore->histheight])
  145. X/*
  146. X * hist_offset tells us, how many lines there are on top of the
  147. X * visible screen.
  148. X */
  149. X
  150. X#define W2D(y) ((y)-hist_offset)
  151. X#define D2W(y) ((y)+hist_offset)
  152. X
  153. static int
  154. linestart(y)
  155. int y;
  156. X{
  157. X  register int x;
  158. X  register char *i;
  159. X
  160. X  for (x = left_mar, i = iWIN(y) + x; x < screenwidth-1; x++)
  161. X    if (*i++ != ' ')
  162. X      break;
  163. X  if (x == screenwidth-1)
  164. X    x = left_mar;
  165. X  return(x);
  166. X}
  167. X
  168. static int
  169. lineend(y)
  170. int y;
  171. X{
  172. X  register int x;
  173. X  register char *i;
  174. X
  175. X  for (x = right_mar, i = iWIN(y) + x; x >= 0; x--)
  176. X    if (*i-- != ' ')
  177. X      break;
  178. X  if (x < 0)
  179. X    x = left_mar;
  180. X  return(x);
  181. X}
  182. X
  183. X/*
  184. X * nextword returnes 1 if x,y altered. dir== -1 means backwards search
  185. X * beginning of a word, +1 means forward search beginning of a word, +2
  186. X * means search forward end of word.
  187. X */
  188. X
  189. X#define NW_BACK        1
  190. X#define NW_ENDOFWORD    2
  191. X#define NW_MUSTMOVE    4
  192. X
  193. static void nextword(xp, yp, dir, num)
  194. int *xp, *yp, dir, num;
  195. X{
  196. X  int xx = screenwidth, yy = fore->histheight + screenheight;
  197. X  register int sx, oq, q, x, y;
  198. X
  199. X  x = *xp;
  200. X  y = *yp;
  201. X  sx = (dir & NW_BACK) ? -1 : 1;
  202. X  if ((dir & NW_ENDOFWORD) && (dir & NW_MUSTMOVE))
  203. X    x += sx;
  204. X  for (oq = -1; ; x += sx, oq = q)
  205. X    {
  206. X      if (x >= xx || x < 0)
  207. X    q = 0;
  208. X      else
  209. X        q = is_letter(iWIN(y)[x]);
  210. X      if (oq >= 0 && oq != q)
  211. X    {
  212. X      if (oq == 0 || !(dir & NW_ENDOFWORD))
  213. X        *xp = x;
  214. X      else
  215. X        *xp = x-sx;
  216. X      *yp = y;
  217. X      if ((!(dir & NW_ENDOFWORD) && q) ||
  218. X          ((dir & NW_ENDOFWORD) && oq))
  219. X        {
  220. X          if (--num <= 0)
  221. X            return;
  222. X        }
  223. X    }
  224. X      if (x == xx)
  225. X    {
  226. X      x = -1;
  227. X      if (++y >= yy)
  228. X        return;
  229. X    }
  230. X      else if (x < 0)
  231. X    {
  232. X      x = xx;
  233. X      if (--y < 0)
  234. X        return;
  235. X    }
  236. X    }
  237. X}
  238. X
  239. X
  240. X/*
  241. X * y1, y2 are WIN coordinates
  242. X *
  243. X * redisplay:    0  -  just copy
  244. X *         1  -  redisplay + copy
  245. X *        2  -  count + copy, don't redisplay
  246. X */
  247. X
  248. static int rem(x1, y1, x2, y2, redisplay, pt, yend)
  249. int x1, y1, x2, y2, redisplay, yend;
  250. char *pt;
  251. X{
  252. X  int i, j, from, to, ry;
  253. X  int l = 0;
  254. X  char *im;
  255. X
  256. X  second = 0;
  257. X  if (y2 < y1 || y2 == y1 && x2 < x1)
  258. X    {
  259. X      i = y2;
  260. X      y2 = y1;
  261. X      y1 = i;
  262. X      i = x2;
  263. X      x2 = x1;
  264. X      x1 = i;
  265. X    }
  266. X  ry = y1 - hist_offset;
  267. X  
  268. X  i = y1;
  269. X  if (redisplay != 2 && pt == 0 && ry <0)
  270. X    {
  271. X      i -= ry;
  272. X      ry = 0;
  273. X    }
  274. X  for (; i <= y2; i++, ry++)
  275. X    {
  276. X      if (redisplay != 2 && pt == 0 && ry > yend)
  277. X    break;
  278. X      from = (i == y1) ? x1 : 0;
  279. X      if (from < left_mar)
  280. X    from = left_mar;
  281. X      for (to = screenwidth-1, im = iWIN(i)+to; to>=0; to--)
  282. X        if (*im-- != ' ')
  283. X      break;
  284. X      if (i == y2 && x2 < to)
  285. X    to = x2;
  286. X      if (to > right_mar)
  287. X    to = right_mar;
  288. X      if (redisplay == 1 && from <= to && ry >=0 && ry <= yend)
  289. X    MarkRedisplayLine(ry, from, to, 0);
  290. X      if (redisplay != 2 && pt == 0)    /* don't count/copy */
  291. X    continue;
  292. X      for (j = from, im = iWIN(i)+from; j <= to; j++)
  293. X    {
  294. X      if (pt)
  295. X        *pt++ = *im++;
  296. X      l++;
  297. X    }
  298. X      if (i != y2)
  299. X    {
  300. X      /* 
  301. X       * this code defines, what glues lines together
  302. X       */
  303. X      switch (nonl)
  304. X        {
  305. X        case 0:        /* lines separated by newlines */
  306. X          if (join_with_cr)
  307. X        {
  308. X          if (pt)
  309. X            *pt++ = '\r';
  310. X          l++;
  311. X        }
  312. X          if (pt)
  313. X        *pt++ = '\n';
  314. X          l++;
  315. X          break;
  316. X        case 1:        /* nothing to separate lines */
  317. X          break;
  318. X        case 2:        /* lines separated by blanks */
  319. X          if (pt)
  320. X        *pt++ = ' ';
  321. X          l++;
  322. X          break;
  323. X        }
  324. X    }
  325. X    }
  326. X  return(l);
  327. X}
  328. X
  329. static int eq(a, b)
  330. int a, b;
  331. X{
  332. X  if (a == b)
  333. X    return 1;
  334. X  if (a == 0 || b == 0)
  335. X    return 1;
  336. X  if (a <= '9' && a >= '0' && b <= '9' && b >= '0')
  337. X    return 1;
  338. X  return 0;
  339. X}
  340. X
  341. int MarkRoutine(flag)    /* return value 1 when copybuffer changed; */
  342. int flag;
  343. X{
  344. X  int x, y, i;
  345. X  hist_offset = fore->histheight;
  346. X  if (!fore->active)
  347. X    {
  348. X      Msg(0, "Fore window is not active !!!");
  349. X      return 0;
  350. X    }
  351. X
  352. X  second = 0;
  353. X  rep_cnt = 0;
  354. X  append_mode = 0;
  355. X  write_buffer = 0;
  356. X  nonl = left_mar = 0;
  357. X  right_mar = screenwidth-1;
  358. X  x = fore->x;
  359. X  y = D2W(fore->y);
  360. X  if (x >= screenwidth)
  361. X    x = screenwidth-1;
  362. X
  363. X  if (flag == TRICKY)
  364. X    {
  365. X      int f, q = 0, xx, yy;
  366. X      char *linep;
  367. X
  368. X      debug2("cursor is at x=%d, y=%d\n", fore->x, D2W(fore->y));
  369. X      for (xx = fore->x - 1, linep = iWIN(y)+xx; xx >= 0; xx--)
  370. X    if ((q = *linep--) != ' ' )
  371. X      break;
  372. X      debug3("%c at (%d,%d)\n", q, xx, y);
  373. X      for (yy = D2W(fore->y) - 1; yy >= 0; yy--)
  374. X    if (xx < 0 || eq(iWIN(yy)[xx], q))
  375. X      {        /* line is matching... */
  376. X        f = 0;
  377. X        for (i = fore->x; i < screenwidth-1; i++)
  378. X          {
  379. X        if (iWIN(yy)[i] != ' ')
  380. X          {
  381. X            f = 1;
  382. X            break;
  383. X          }
  384. X          }
  385. X        if (f)
  386. X          break;
  387. X      }
  388. X      if (yy < 0)
  389. X    return 0;
  390. X      xx = 0;
  391. X      for (i = screenwidth-1, linep = iWIN(yy)+i; i>0; i--)
  392. X    if (*linep-- != ' ')
  393. X      break;
  394. X      if (i < x)
  395. X    i = x;
  396. X      if (copybuffer != NULL)
  397. X    Free(copybuffer);
  398. X      if ((copybuffer = malloc((unsigned) (i - x + 2))) == NULL)
  399. X    {
  400. X      Msg(0, "Not enough memoooh!... Sorry.");
  401. X      return 0;
  402. X    }
  403. X      rem(x, yy, i, yy, 0, copybuffer, 0);
  404. X      copylen = i - x + 1;
  405. X      return 1;
  406. X    }
  407. X  InitOverlayPage(process_mark_input, MarkRedisplayLine, MarkRewrite, 1);
  408. X  GotoPos(x, W2D(y));
  409. X#ifdef NETHACK
  410. X  if (nethackflag)
  411. X    Msg(0, "Welcome to hacker's treasure zoo - Column %d Line %d(+%d) (%d,%d)",
  412. X    x+1, W2D(y+1), fore->histheight, fore->width, fore->height);
  413. X  else
  414. X#endif
  415. X  Msg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)",
  416. X      x+1, W2D(y+1), fore->histheight, fore->width, fore->height);
  417. X  fflush(stdout);
  418. X  cx = x1 = x;
  419. X  cy = y1 = y;
  420. X  in_mark = 1;
  421. X  return 0;
  422. X}
  423. X
  424. static void process_mark_input(inbufp,inlenp)
  425. char **inbufp;
  426. int *inlenp;
  427. X{
  428. X  char *inbuf, *pt;
  429. X  int inlen;
  430. X  int x2, y2, i, j, yend;
  431. X  int newcopylen = 0, od;
  432. X/*
  433. X  char *extrap = 0, extrabuf[100];
  434. X*/
  435. X      
  436. X  if (inbufp == 0)
  437. X    {
  438. X      AbortMarkRoutine();
  439. X      return;
  440. X    }
  441. X  inbuf= *inbufp;
  442. X  inlen= *inlenp;
  443. X  pt = inbuf;
  444. X  while (in_mark && (inlen /* || extrap */))
  445. X    {
  446. X      if (!HS)
  447. X    RemoveStatus();
  448. X/*
  449. X      if (extrap)
  450. X    {
  451. X      od = *extrap++;
  452. X      if (*extrap == 0)
  453. X        extrap = 0;
  454. X    }
  455. X      else
  456. X*/
  457. X    {
  458. X          od = mark_key_tab[*pt++];
  459. X          inlen--;
  460. X    }
  461. X      if (od >= '0' && od <= '9')
  462. X        {
  463. X      if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0))
  464. X        {
  465. X          rep_cnt = 10 * rep_cnt + od - '0';
  466. X          continue;
  467. X           /*
  468. X           * Now what is that 1001 here? Well, we have a screen with
  469. X           * 25 * 80 = 2000 characters. Movement is at most across the full
  470. X           * screen. This we do with word by word movement, as character by
  471. X           * character movement never steps over line boundaries. The most words
  472. X           * we can place on the screen are 1000 single letter words. Thus 1001
  473. X           * is sufficient. Users with bigger screens never write in single letter
  474. X           * words, as they should be more advanced. jw.
  475. X           * Oh, wrong. We still give even the experienced user a factor of ten.
  476. X           */
  477. X        }
  478. X    }
  479. X      switch (od)
  480. X    {
  481. X    case '\014':    /* CTRL-L Redisplay */
  482. X      Redisplay();
  483. X      GotoPos(cx, W2D(cy));
  484. X      break;
  485. X    case '\010':    /* CTRL-H Backspace */
  486. X    case 'h':
  487. X      if (rep_cnt == 0)
  488. X        rep_cnt = 1;
  489. X      revto(cx - rep_cnt, cy);
  490. X      break;
  491. X    case '\016':    /* CTRL-N */
  492. X    case 'j':
  493. X      if (rep_cnt == 0)
  494. X        rep_cnt = 1;
  495. X      revto(cx, cy + rep_cnt);
  496. X      break;
  497. X    case '+':
  498. X      if (rep_cnt == 0)
  499. X        rep_cnt = 1;
  500. X      j = cy + rep_cnt;
  501. X      if (j > fore->histheight + screenheight - 1)
  502. X        j = fore->histheight + screenheight - 1;
  503. X      revto(linestart(j), j);
  504. X      break;
  505. X    case '-':
  506. X      if (rep_cnt == 0)
  507. X        rep_cnt = 1;
  508. X      j = cy - rep_cnt;
  509. X      if (j < 0)
  510. X        j = 0;
  511. X      revto(linestart(j), j);
  512. X      break;
  513. X    case '^':
  514. X      revto(linestart(cy), cy);
  515. X      break;
  516. X    case '\n':
  517. X      revto(left_mar, cy + 1);
  518. X      break;
  519. X    case 'k':
  520. X    case '\020':    /* CTRL-P */
  521. X      if (rep_cnt == 0)
  522. X        rep_cnt = 1;
  523. X      revto(cx, cy - rep_cnt);
  524. X      break;
  525. X    case 'l':
  526. X      if (rep_cnt == 0)
  527. X        rep_cnt = 1;
  528. X      revto(cx + rep_cnt, cy);
  529. X      break;
  530. X    case '\001':    /* CTRL-A from tcsh/emacs */
  531. X    case '0':
  532. X      revto(left_mar, cy);
  533. X      break;
  534. X    case '\004':    /* CTRL-D down half screen */
  535. X      if (rep_cnt == 0)
  536. X        rep_cnt = (screenheight+1) >> 1;
  537. X      revto_line(cx, cy + rep_cnt, W2D(cy));
  538. X      break;
  539. X    case '$':
  540. X      revto(lineend(cy), cy);
  541. X      break;
  542. X    case '\025':    /* CTRL-U up half screen */
  543. X      if (rep_cnt == 0)
  544. X        rep_cnt = (screenheight+1) >> 1;
  545. X      revto_line(cx, cy - rep_cnt, W2D(cy));
  546. X      break;
  547. X    case '?':
  548. X      if (left_mar == 0 && right_mar == screenwidth - 1)
  549. X        Msg(0, "Column %d Line %d(+%d)", cx+1, W2D(cy)+1,
  550. X        hist_offset);
  551. X      else
  552. X        Msg(0, "Column %d(%d..%d) Line %d(+%d)", cx+1,
  553. X        left_mar+1, right_mar+1, W2D(cy)+1, hist_offset);
  554. X      break;
  555. X    case '\002':    /* CTRL-B  back one page */
  556. X      if (rep_cnt == 0)
  557. X        rep_cnt = 1;
  558. X      rep_cnt *= (screenheight-1);
  559. X      revto(cx, cy - rep_cnt);
  560. X      break;
  561. X    case '\006':    /* CTRL-F  forward one page */
  562. X      if (rep_cnt == 0)
  563. X        rep_cnt = 1;
  564. X      rep_cnt *= (screenheight-1);
  565. X      revto(cx, cy + rep_cnt);
  566. X      break;
  567. X    case '\005':    /* CTRL-E  scroll up */
  568. X      if (rep_cnt == 0)
  569. X        rep_cnt = 1;
  570. X      rep_cnt = MarkScrollUpDisplay(rep_cnt);
  571. X      if (cy < D2W(0))
  572. X            revto(cx, D2W(0));
  573. X      else
  574. X            GotoPos(cx, W2D(cy));
  575. X      break;
  576. X    case '\031': /* CTRL-Y  scroll down */
  577. X      if (rep_cnt == 0)
  578. X        rep_cnt = 1;
  579. X      rep_cnt = MarkScrollDownDisplay(rep_cnt);
  580. X      if (cy > D2W(screenheight-1))
  581. X            revto(cx, D2W(screenheight-1));
  582. X      else
  583. X            GotoPos(cx, W2D(cy));
  584. X      break;
  585. X    case '@':
  586. X      /* it may be usefull to have a key that does nothing */
  587. X      break;
  588. X    case '%':
  589. X      rep_cnt--;
  590. X      /* rep_cnt is a percentage for the history buffer */
  591. X      if (rep_cnt < 0)
  592. X        rep_cnt = 0;
  593. X      if (rep_cnt > 100)
  594. X        rep_cnt = 100;
  595. X      revto_line(left_mar, (rep_cnt * (fore->histheight + screenheight)) / 100, (screenheight-1)/2);
  596. X      break;
  597. X    case 'g':
  598. X      rep_cnt = 1;
  599. X      /* FALLTHROUGH */
  600. X    case 'G':
  601. X      /* rep_cnt is here the WIN line number */
  602. X      if (rep_cnt == 0)
  603. X        rep_cnt = fore->histheight + screenheight;
  604. X      revto_line(left_mar, --rep_cnt, (screenheight-1)/2);
  605. X      break;
  606. X    case 'H':
  607. X      revto(left_mar, D2W(0));
  608. X      break;
  609. X    case 'M':
  610. X      revto(left_mar, D2W((screenheight-1) / 2));
  611. X      break;
  612. X    case 'L':
  613. X      revto(left_mar, D2W(screenheight-1));
  614. X      break;
  615. X    case '|':
  616. X      revto(--rep_cnt, cy);
  617. X      break;
  618. X    case 'w':
  619. X      i = cx;
  620. X      j = cy;
  621. X      if (rep_cnt == 0)
  622. X        rep_cnt = 1;
  623. X      nextword(&i, &j, NW_MUSTMOVE, rep_cnt);
  624. X      revto(i, j);
  625. X      break;
  626. X    case 'e':
  627. X      i = cx;
  628. X      j = cy;
  629. X      if (rep_cnt == 0)
  630. X        rep_cnt = 1;
  631. X      nextword(&i, &j, NW_ENDOFWORD|NW_MUSTMOVE, rep_cnt);
  632. X      revto(i, j);
  633. X      break;
  634. X    case 'b':
  635. X      i = cx;
  636. X      j = cy;
  637. X      if (rep_cnt == 0)
  638. X        rep_cnt = 1;
  639. X      nextword(&i, &j, NW_BACK|NW_ENDOFWORD|NW_MUSTMOVE, rep_cnt);
  640. X      revto(i, j);
  641. X      break;
  642. X    case 'a':
  643. X      append_mode = 1 - append_mode;
  644. X      debug1("append mode %d--\n", append_mode);
  645. X      Msg(0, (append_mode) ? ":set append" : ":set noappend");
  646. X      break;
  647. X    case 'v':
  648. X    case 'V':
  649. X      /* this sets start column to column 9 for VI :set nu users */
  650. X      if (left_mar == 8)
  651. X        rep_cnt = 1;
  652. X      else
  653. X        rep_cnt = 9;
  654. X      /* FALLTHROUGH */
  655. X    case 'c':
  656. X    case 'C':
  657. X      /* set start column (c) and end column (C) */
  658. X      if (second)
  659. X        {
  660. X          rem(x1, y1, cx, cy, 1, 0, screenheight-1); /* Hack */
  661. X          second = 1;    /* rem turns off second */
  662. X        }
  663. X      rep_cnt--;
  664. X      if (rep_cnt < 0)
  665. X        rep_cnt = cx;
  666. X      if (od != 'C')
  667. X        {
  668. X          left_mar = rep_cnt;
  669. X          if (left_mar > right_mar)
  670. X        left_mar = right_mar;
  671. X        }
  672. X      else
  673. X        {
  674. X          right_mar = rep_cnt;
  675. X          if (left_mar > right_mar)
  676. X        right_mar = left_mar;
  677. X        }
  678. X      if (second)
  679. X        {
  680. X          int x = cx, y = cy;
  681. X          cx = x1; cy = y1;
  682. X          revto(x, y);
  683. X        }
  684. X      if (od == 'v' || od == 'V')
  685. X        Msg(0, (left_mar != 8) ? ":set nonu" : ":set nu");
  686. X      break;
  687. X    case 'J':
  688. X      /* how do you join lines in VI ? */
  689. X      nonl = (nonl + 1) % 3;
  690. X      switch (nonl)
  691. X        {
  692. X        case 0:
  693. X          if (join_with_cr)
  694. X        Msg(0, "Multiple lines (CR/LF)");
  695. X          else
  696. X        Msg(0, "Multiple lines (LF)");
  697. X          break;
  698. X        case 1:
  699. X          Msg(0, "Lines joined");
  700. X          break;
  701. X        case 2:
  702. X          Msg(0, "Lines joined with blanks");
  703. X          break;
  704. X        }
  705. X      break;
  706. X    case 'y':
  707. X    case 'Y':
  708. X      if (!second)
  709. X        {
  710. X          revto(linestart(cy), cy);
  711. X          second++;
  712. X          x1 = cx;
  713. X          y1 = cy;
  714. X        }
  715. X      if (--rep_cnt > 0)
  716. X        revto(cx, cy + rep_cnt);
  717. X      revto(lineend(cy), cy);
  718. X      if (od == 'y')
  719. X        break;
  720. X      /* FALLTHROUGH */
  721. X    case 'W':
  722. X      if (od == 'W')
  723. X        {
  724. X          if (rep_cnt == 0)
  725. X        rep_cnt = 1;
  726. X          if (!second)
  727. X        {
  728. X          i = cx;
  729. X          j = cy;
  730. X          nextword(&i, &j, NW_BACK|NW_ENDOFWORD, 1);
  731. X          revto(i, j);
  732. X          second++;
  733. X          x1 = cx;
  734. X          y1 = cy;
  735. X        }
  736. X          i = cx;
  737. X          j = cy;
  738. X          nextword(&i, &j, NW_ENDOFWORD, rep_cnt);
  739. X          revto(i, j);
  740. X        }
  741. X      /* FALLTHROUGH */
  742. X    case 'A':
  743. X      if (od == 'A')
  744. X        append_mode = 1;
  745. X      /* FALLTHROUGH */
  746. X    case '>':
  747. X      if (od == '>')
  748. X        write_buffer = 1;
  749. X      /* FALLTHROUGH */
  750. X    case ' ':
  751. X    case '\r':
  752. X      if (!second)
  753. X        {
  754. X          second++;
  755. X          x1 = cx;
  756. X          y1 = cy;
  757. X          revto(x1, y1);
  758. X#ifdef NETHACK
  759. X          if (nethackflag)
  760. X        Msg(0, "You drop a magic marker - Column %d Line %d",
  761. X                cx+1, W2D(cy)+1, hist_offset);
  762. X          else
  763. X#endif
  764. X          Msg(0, "First mark set - Column %d Line %d", cx+1, cy+1);
  765. X          break;
  766. X        }
  767. X      else
  768. X        {
  769. X          x2 = cx;
  770. X          y2 = cy;
  771. X          newcopylen = rem(x1, y1, x2, y2, 2, 0, 0); /* count */
  772. X          if (copybuffer != NULL && !append_mode)
  773. X        {
  774. X          copylen = 0;
  775. X          Free(copybuffer);
  776. X        }
  777. X          if (newcopylen > 0)
  778. X        {
  779. X          /* the +3 below is for : cr + lf + \0 */
  780. X          if (copybuffer != NULL)
  781. X            copybuffer = realloc(copybuffer,
  782. X            (unsigned) (copylen + newcopylen + 3));
  783. X          else
  784. X            {
  785. X            copylen = 0;
  786. X            copybuffer = malloc((unsigned) (newcopylen + 3));
  787. X            }
  788. X          if (copybuffer == NULL)
  789. X            {
  790. X              AbortMarkRoutine();
  791. X              Msg(0, "Not enough memoooh!... Sorry.");
  792. X              copylen = 0;
  793. X              copybuffer = NULL;
  794. X              break;
  795. X            }
  796. X          if (append_mode)
  797. X            {
  798. X              switch (nonl)
  799. X            /* 
  800. X             * this code defines, what glues lines together
  801. X             */
  802. X            {
  803. X            case 0:
  804. X              if (join_with_cr)
  805. X                {
  806. X                  copybuffer[copylen] = '\r';
  807. X                  copylen++;
  808. X                }
  809. X              copybuffer[copylen] = '\n';
  810. X              copylen++;
  811. X              break;
  812. X            case 1:
  813. X              break;
  814. X            case 2:
  815. X              copybuffer[copylen] = ' ';
  816. X              copylen++;
  817. X              break;
  818. X            }
  819. X            }
  820. X          yend = screenheight - 1;
  821. X          if (fore->histheight - hist_offset < screenheight)
  822. X            {
  823. X              second = 0;
  824. X              yend -= MarkScrollUpDisplay(fore->histheight - hist_offset);
  825. X            }
  826. X          copylen += rem(x1, y1, x2, y2, hist_offset == fore->histheight, copybuffer + copylen, yend);
  827. X        }
  828. X          if (hist_offset != fore->histheight)
  829. X        {
  830. X          in_ovl = 0;    /* So we can use Activate() */
  831. X          Activate();
  832. X        }
  833. X          ExitOverlayPage();
  834. X          if (append_mode)
  835. X        Msg(0, "Appended %d characters to buffer",
  836. X            newcopylen);
  837. X          else
  838. X        Msg(0, "Copied %d characters into buffer", copylen);
  839. X          if (write_buffer)
  840. X        WriteFile(DUMP_EXCHANGE);
  841. X          in_mark = 0;
  842. X          break;
  843. X        }
  844. X    default:
  845. X      AbortMarkRoutine();
  846. X#ifdef NETHACK
  847. X      if (nethackflag)
  848. X        Msg(0, "You escaped the dungeon.");
  849. X      else
  850. X#endif
  851. X      Msg(0, "Copy mode aborted");
  852. X      break;
  853. X    }
  854. X      rep_cnt = 0;
  855. X    }
  856. X  fflush(stdout);
  857. X  *inbufp = pt;
  858. X  *inlenp = inlen;
  859. X}
  860. X
  861. static void revto(tx, ty)
  862. int tx, ty;
  863. X{
  864. X  revto_line(tx, ty, -1);
  865. X}
  866. X
  867. X/* tx, ty: WINDOW,  line: DISPLAY */
  868. static void revto_line(tx, ty, line)
  869. int tx, ty, line;
  870. X{
  871. X  int fx, fy;
  872. X  int x, y, t, revst, reven, qq, ff, tt, st, en, ce = 0;
  873. X  int ystart = 0, yend = screenheight-1;
  874. X  int i, ry;
  875. X  if (tx < 0)
  876. X    tx = 0;
  877. X  else if (tx > screenwidth - 1)
  878. X    tx = screenwidth -1;
  879. X  if (ty < 0)
  880. X    ty = 0;
  881. X  else if (ty > fore->histheight + screenheight - 1)
  882. X    ty = fore->histheight + screenheight - 1;
  883. X  
  884. X  fx = cx; fy = cy;
  885. X  cx = tx; cy = ty;
  886. X/*debug2("revto(%d, %d, ", x1, y1);
  887. X  debug2("%d, %d, ", fx, fy);
  888. X  debug2("%d, %d)\n", tx, ty);*/
  889. X  /*
  890. X   * if we go to a position that is currently offscreen 
  891. X   * then scroll the screen
  892. X   */
  893. X  i = 0;
  894. X  if (line >= 0 && line < screenheight)
  895. X    i = W2D(ty) - line;
  896. X  else if (ty < hist_offset)
  897. X    i = ty - hist_offset;
  898. X  else if (ty > hist_offset + (screenheight-1))
  899. X    i = ty-hist_offset-(screenheight-1);
  900. X  if (i > 0)
  901. X    yend -= MarkScrollUpDisplay(i);
  902. X  else if (i < 0)
  903. X    ystart += MarkScrollDownDisplay(-i);
  904. X
  905. X  if (second == 0)
  906. X    {
  907. X      GotoPos(tx, W2D(cy));
  908. X      return;
  909. X    }
  910. X  
  911. X  qq = x1 + y1 * screenwidth;
  912. X  ff = fx + fy * screenwidth; /* "from" offset in WIN coords */
  913. X  tt = tx + ty * screenwidth; /* "to" offset  in WIN coords*/
  914. X  if (ff > tt)
  915. X    {
  916. X      st = tt; en = ff;
  917. X      x = tx; y = ty;
  918. X    }
  919. X  else
  920. X    {
  921. X      st = ff; en = tt;
  922. X      x = fx; y = fy;
  923. X    }
  924. X  if (st > qq)
  925. X    {
  926. X      st++;
  927. X      x++;
  928. X    }
  929. X  if (en < qq)
  930. X    en--;
  931. X  if (tt > qq)
  932. X    {
  933. X      revst = qq; reven = tt;
  934. X    }
  935. X  else
  936. X    {
  937. X      revst = tt; reven = qq;
  938. X    }
  939. X  ry = y - hist_offset;
  940. X  if (ry < ystart)
  941. X    {
  942. X      y += (ystart - ry);
  943. X      x = 0;
  944. X      st = y * screenwidth;
  945. X      ry = ystart;
  946. X    }
  947. X  for (t = st; t <= en; t++, x++)
  948. X    {
  949. X      if (x >= screenwidth)
  950. X    {
  951. X      x = 0;
  952. X      y++, ry++;
  953. X    }
  954. X      if (ry > yend)
  955. X    break;
  956. X      if (t == st || x == 0)
  957. X    {
  958. X      for (ce = screenwidth-1; ce >= 0; ce--)
  959. X        if (iWIN(y)[ce] != ' ')
  960. X          break;
  961. X    }
  962. X      if (x <= ce && x >= left_mar && x <= right_mar
  963. X          && (LP || x < screenwidth-1 || ry < screenbot))
  964. X    {
  965. X      GotoPos(x, W2D(y));
  966. X      if (t >= revst && t <= reven)
  967. X        SaveSetAttr(A_SO, ASCII);
  968. X      else
  969. X        SaveSetAttr(aWIN(y)[x], fWIN(y)[x]);
  970. X      PUTCHAR(iWIN(y)[x]);
  971. X    }
  972. X    }
  973. X  GotoPos(tx, W2D(cy));
  974. X}
  975. X
  976. static void AbortMarkRoutine()
  977. X{
  978. X  int yend, redisp;
  979. X
  980. X  yend = screenheight - 1;
  981. X  redisp = second;
  982. X  if (fore->histheight - hist_offset < screenheight)
  983. X    {
  984. X      second = 0;
  985. X      yend -= MarkScrollUpDisplay(fore->histheight - hist_offset);
  986. X    }
  987. X  if (hist_offset != fore->histheight)
  988. X    {
  989. X      in_ovl = 0;    /* So we can use Activate() */
  990. X      Activate();    /* to do a complete redisplay */
  991. X    }
  992. X  else
  993. X    {
  994. X      rem(x1, y1, cx, cy, redisp, 0, yend);
  995. X    }
  996. X  ExitOverlayPage();
  997. X  in_mark = 0;
  998. X}
  999. X
  1000. X
  1001. static void MarkRedisplayLine(y, xs, xe, isblank)
  1002. int y; /* NOTE: y is in DISPLAY coords system! */
  1003. int xs, xe;
  1004. int isblank;
  1005. X{
  1006. X  int x, i, rm;
  1007. X  int sta, sto, cp; /* NOTE: these 3 are in WINDOW coords system */
  1008. X  char *wi, *wa, *wf, *oldi;
  1009. X  InsertMode(0); /* Not done in DisplayLine() */
  1010. X
  1011. X  wi = iWIN(D2W(y));
  1012. X  wa = aWIN(D2W(y));
  1013. X  wf = fWIN(D2W(y));
  1014. X  oldi = isblank ? blank : null;
  1015. X  if (second == 0)
  1016. X    {
  1017. X      DisplayLine(oldi, null, null, wi, wa, wf, y, xs, xe);
  1018. X      return;
  1019. X    }
  1020. X  sta = y1 * screenwidth + x1;
  1021. X  sto = cy * screenwidth + cx;
  1022. X  if (sta > sto)
  1023. X    {
  1024. X      i=sta; sta=sto; sto=i;
  1025. X    }
  1026. X  cp = D2W(y) * screenwidth + xs;
  1027. X  rm = right_mar;
  1028. X  for (x=screenwidth-1; x>=0; x--)
  1029. X    if (wi[x] != ' ')
  1030. X      break;
  1031. X  if (x < rm)
  1032. X    rm = x;
  1033. X  for (x=xs; x<=xe; x++, cp++)
  1034. X    if (cp>=sta && x>= left_mar)
  1035. X      break;
  1036. X  if (x>xs)
  1037. X    DisplayLine(oldi, null, null, wi, wa, wf, y, xs, x-1);
  1038. X  for (; x<=xe; x++, cp++)
  1039. X    {
  1040. X      if (cp > sto || x > rm || (!LP && x >= screenwidth-1 && y == screenbot))
  1041. X    break;
  1042. X      GotoPos(x, y);
  1043. X      SaveSetAttr(A_SO, ASCII);
  1044. X      PUTCHAR(wi[x]);
  1045. X    }
  1046. X  if (x<=xe)
  1047. X    DisplayLine(oldi, null, null, wi, wa, wf, y, x, xe);
  1048. X}
  1049. X
  1050. X
  1051. static int
  1052. MarkRewrite(ry, xs, xe, doit)
  1053. int ry, xs, xe, doit;
  1054. X{
  1055. X  int dx, x, y, st, en, t, rm;
  1056. X  char *a, *f, *i;
  1057. X
  1058. X  y = D2W(ry);
  1059. X  dx = xe - xs;
  1060. X  if (doit)
  1061. X    {
  1062. X      i = iWIN(y) + xs;
  1063. X      while (dx--)
  1064. X        PUTCHAR(*i++);
  1065. X      return(0);
  1066. X    }
  1067. X  
  1068. X  a = aWIN(y) + xs,
  1069. X  f = fWIN(y) + xs;
  1070. X  if (second == 0)
  1071. X    st = en = -1;
  1072. X  else
  1073. X    {
  1074. X      st = y1 * screenwidth + x1;
  1075. X      en = cy * screenwidth + cx;
  1076. X      if (st > en)
  1077. X        {
  1078. X          t = st; st = en; en = t;
  1079. X        }
  1080. X    }
  1081. X  t = y * screenwidth + xs;
  1082. X  for (rm=screenwidth-1, i=iWIN(y) + screenwidth-1; rm>=0; rm--)
  1083. X    if (*i-- != ' ')
  1084. X      break;
  1085. X  if (rm > right_mar)
  1086. X    rm = right_mar;
  1087. X  x = xs;
  1088. X  while (dx--)
  1089. X    {
  1090. X      if (t >= st && t <= en && x >= left_mar && x <= rm)
  1091. X        {
  1092. X      if (GlobalAttr != A_SO || GlobalCharset != ASCII)
  1093. X        return(EXPENSIVE);
  1094. X        }
  1095. X      else
  1096. X        {
  1097. X      if (GlobalAttr != *a || GlobalCharset != *f)
  1098. X        return(EXPENSIVE);
  1099. X        }
  1100. X      a++, f++, t++, x++;
  1101. X    }
  1102. X  return(xe - xs);
  1103. X}
  1104. X
  1105. X
  1106. X/*
  1107. X * scroll the screen contents up/down.
  1108. X */
  1109. static int MarkScrollUpDisplay(n)
  1110. int n;
  1111. X{
  1112. X  int i;
  1113. X  debug1("MarkScrollUpDisplay(%d)\n", n);
  1114. X  if (n <= 0)
  1115. X    return 0;
  1116. X  if (n > fore->histheight - hist_offset)
  1117. X    n = fore->histheight - hist_offset;
  1118. X  i = (n < screenheight) ? n : (screenheight);
  1119. X  ScrollRegion(0, screenheight - 1, i);
  1120. X  hist_offset += n;
  1121. X  while (i-- > 0)
  1122. X    MarkRedisplayLine(screenheight-i-1, 0, screenwidth-1, 1);
  1123. X  return n;
  1124. X}
  1125. X
  1126. static int MarkScrollDownDisplay(n)
  1127. int n;
  1128. X{
  1129. X  int i;
  1130. X  debug1("MarkScrollDownDisplay(%d)\n", n);
  1131. X  if (n <= 0)
  1132. X    return 0;
  1133. X  if (n > hist_offset)
  1134. X    n = hist_offset;
  1135. X  i = (n < screenheight) ? n : (screenheight);
  1136. X  ScrollRegion(0, screenheight - 1, -i);
  1137. X  hist_offset -= n;
  1138. X  while (i-- > 0)
  1139. X    MarkRedisplayLine(i, 0, screenwidth-1, 1);
  1140. X  return n;
  1141. X}
  1142. X
  1143. END_OF_FILE
  1144. if test 25040 -ne `wc -c <'mark.c'`; then
  1145.     echo shar: \"'mark.c'\" unpacked with wrong size!
  1146. fi
  1147. # end of 'mark.c'
  1148. fi
  1149. if test -f 'socket.c' -a "${1}" != "-c" ; then 
  1150.   echo shar: Will not clobber existing file \"'socket.c'\"
  1151. else
  1152. echo shar: Extracting \"'socket.c'\" \(25596 characters\)
  1153. sed "s/^X//" >'socket.c' <<'END_OF_FILE'
  1154. X/* Copyright (c) 1991
  1155. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  1156. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  1157. X * Copyright (c) 1987 Oliver Laumann
  1158. X *
  1159. X * This program is free software; you can redistribute it and/or modify
  1160. X * it under the terms of the GNU General Public License as published by
  1161. X * the Free Software Foundation; either version 1, or (at your option)
  1162. X * any later version.
  1163. X *
  1164. X * This program is distributed in the hope that it will be useful,
  1165. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1166. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1167. X * GNU General Public License for more details.
  1168. X *
  1169. X * You should have received a copy of the GNU General Public License
  1170. X * along with this program (see the file COPYING); if not, write to the
  1171. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1172. X *
  1173. X * Noteworthy contributors to screen's design and implementation:
  1174. X *    Wayne Davison (davison@borland.com)
  1175. X *    Patrick Wolfe (pat@kai.com, kailand!pat)
  1176. X *    Bart Schaefer (schaefer@cse.ogi.edu)
  1177. X *    Nathan Glasser (nathan@brokaw.lcs.mit.edu)
  1178. X *    Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
  1179. X *    Howard Chu (hyc@hanauma.jpl.nasa.gov)
  1180. X *    Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
  1181. X *    Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
  1182. X *    Marc Boucher (marc@CAM.ORG)
  1183. X *
  1184. X ****************************************************************
  1185. X */
  1186. X
  1187. X#ifndef lint
  1188. X  static char rcs_id[] = "$Id: socket.c,v 1.55 91/10/11 11:24:38 jnweiger Exp $ FAU";
  1189. X#endif
  1190. X
  1191. X#include "config.h"
  1192. X#if defined(MIPS) || defined(GOULD_NP1) || defined(B43)
  1193. extern int errno;
  1194. X#endif
  1195. X#if defined(BSD) || defined(sequent) || defined(pyr)
  1196. X# include <strings.h>
  1197. X#else
  1198. X# include <string.h>
  1199. X#endif
  1200. X#include <sys/types.h>
  1201. X#include <sys/stat.h>
  1202. X#include <sys/file.h>
  1203. X#ifndef NAMEDPIPE
  1204. X#include <sys/socket.h>
  1205. X#endif
  1206. X#include <fcntl.h>
  1207. X#ifndef NAMEDPIPE
  1208. X#include <sys/un.h>
  1209. X#endif
  1210. X#include <signal.h>
  1211. X#include <sys/time.h>
  1212. X#ifdef DIRENT
  1213. X# include <sys/param.h>
  1214. X# include <dirent.h>
  1215. X#else
  1216. X# include <sys/dir.h>
  1217. X# define dirent direct
  1218. X#endif
  1219. X#ifdef USEVARARGS
  1220. X# if defined(__STDC__)
  1221. X#  include <stdarg.h>
  1222. X# else
  1223. X#  include <varargs.h>
  1224. X# endif
  1225. X#endif
  1226. X#include "screen.h"
  1227. X#include "extern.h"
  1228. X
  1229. X#if defined(_SEQUENT_) && !defined(NAMEDPIPE)
  1230. X# define connect sconnect    /* _SEQUENT_ has braindamaged connect */
  1231. X#endif
  1232. X
  1233. extern char *RcFileName, *extra_incap, *extra_outcap;
  1234. extern WinList, Detached, ServerSocket, real_uid, real_gid, eff_uid, eff_gid;
  1235. X#ifdef BSDJOBS
  1236. extern int Suspended;
  1237. X#endif
  1238. extern AttacherPid, dflag, mflag, rflag, lsflag, quietflag, wipeflag;
  1239. extern char HostName[];
  1240. extern struct mode OldMode, NewMode;
  1241. extern struct win *wtab[], *fore;
  1242. X#ifdef NETHACK
  1243. extern nethackflag;
  1244. X#endif
  1245. X
  1246. X#ifdef PASSWORD
  1247. extern int CheckPassword;
  1248. extern char Password[];
  1249. X#endif
  1250. X#if !defined(POSIX) && defined(BSDJOBS)
  1251. extern DevTty;
  1252. X#endif
  1253. extern char *getenv(), *GetTtyName();
  1254. X
  1255. char SockPath[MAXPATH];
  1256. char *SockNamePtr, *SockName;
  1257. X
  1258. char *strdup(str)
  1259. const char *str;
  1260. X{
  1261. X  char *ret;
  1262. X
  1263. X  if ((ret = (char *) malloc((unsigned) (strlen(str) + 1))) == 0)
  1264. X    {
  1265. X      Msg_nomem;
  1266. X      return (0);
  1267. X    }
  1268. X  (void) strcpy(ret, str);
  1269. X  return (ret);
  1270. X}
  1271. X
  1272. int RecoverSocket()
  1273. X{
  1274. X  int s = 0, d;
  1275. X
  1276. X  (void) unlink(SockPath);
  1277. X  s = MakeServerSocket();
  1278. X  if (s != ServerSocket)
  1279. X    {
  1280. X      debug2("Oh, Serversocket was %d, now %d, let's dup!\n", ServerSocket, s);
  1281. X      d = dup2(s, ServerSocket);
  1282. X      close(s);
  1283. X      if (d != ServerSocket)
  1284. X    {
  1285. X      debug2("Hmm, dup2() failed, Serversocket was %d, now %d, bye\n",
  1286. X         ServerSocket, d);
  1287. X      return 0;
  1288. X    }
  1289. X    }
  1290. X  if (Detached)
  1291. X    (void) chmod(SockPath, /* S_IFSOCK | */ 0600); /* Flag detached-ness */
  1292. X  return 1;
  1293. X}
  1294. X
  1295. X
  1296. X/* socket mode 700 means we are Attached. 600 is detached.
  1297. X * we return how many sockets we found. if it was exactly one, we come
  1298. X * back with a SockPath set to it and open it in a fd pointed to by fdp.
  1299. X * if fdp == 0 we simply produce a list if all sockets.
  1300. X */
  1301. int FindSocket(how, fdp)
  1302. int how;
  1303. int *fdp;
  1304. X{
  1305. X  register int s, lasts = 0, found = 0, deadcount = 0, wipecount = 0;
  1306. X  register DIR *dirp;
  1307. X  register struct dirent *dp;
  1308. X  struct stat st;
  1309. X  struct foundsock
  1310. X    {
  1311. X      char *name;
  1312. X      int mode;
  1313. X    }         foundsock[100];    /* 100 is hopefully enough. */
  1314. X  int foundsockcount = 0;
  1315. X
  1316. X  if (SockName && fdp)
  1317. X    {
  1318. X      if ((lasts = MakeClientSocket(0, SockName)) == -1)
  1319. X    {
  1320. X      if (quietflag)
  1321. X        eexit(10);
  1322. X      else
  1323. X        {
  1324. X          if (how == MSG_CONT)
  1325. X            Msg(0, "Attach failed.");
  1326. X          else
  1327. X            Msg(0, "There is no screen to be %sed from %s.",
  1328. X                dflag ? "detach" : "resum", SockName);
  1329. X        }
  1330. X    }
  1331. X      debug1("FindSocket likes what You specified('%s');\n", SockPath);
  1332. X      *fdp = lasts;
  1333. X      return 1;
  1334. X    }
  1335. X
  1336. X  /* user gave no SockName, so we really have to search */
  1337. X#ifdef NFS_HACK
  1338. X  setreuid(eff_uid, real_uid);
  1339. X#endif
  1340. X  debug1("FindSock searching... '%s'\n", SockPath);
  1341. X  if ((dirp = opendir(SockPath)) == NULL)
  1342. X    Msg(0, "Cannot opendir %s", SockPath);
  1343. X  while ((dp = readdir(dirp)) != NULL)
  1344. X    {
  1345. X      SockName = dp->d_name;
  1346. X      if (SockName[0] == '.')
  1347. X    continue;
  1348. X      debug1("Attach found: '%s'\n", SockName);
  1349. X      /*
  1350. X       * ATTENTION! MakeClientSocket adds SockName to SockPath! anyway, we
  1351. X       * need it earlier.
  1352. X       */
  1353. X      strcpy(SockNamePtr, SockName);
  1354. X      if (stat(SockPath, &st) == -1)
  1355. X    Msg(errno, "stat");
  1356. X      if (st.st_uid != real_uid)
  1357. X    continue;
  1358. X      foundsock[foundsockcount].name = strdup(SockName);
  1359. X      foundsock[foundsockcount].mode = s = st.st_mode & 0777;
  1360. X      debug2("FindSocket: %s has mode %04o...\n", SockName, s);
  1361. X      if (s == 0700 || s == 0600)
  1362. X    {
  1363. X      /* we try to connect through the socket. if successfull, 
  1364. X       * thats o.k. otherwise we record that mode as -1.
  1365. X       */
  1366. X      if ((s = MakeClientSocket(0, SockName)) == -1)
  1367. X        { 
  1368. X          foundsock[foundsockcount].mode = -1;
  1369. X          deadcount++;
  1370. X        }
  1371. X      else
  1372. X        close(s);
  1373. X    }
  1374. X      if (++foundsockcount >= 100)
  1375. X    break;
  1376. X    }
  1377. X  closedir(dirp);
  1378. X#ifdef NFS_HACK
  1379. X  setreuid(real_uid, eff_uid);
  1380. X#endif
  1381. X
  1382. X  if (wipeflag)
  1383. X    {
  1384. X      for (s = 0; s < foundsockcount; s++)
  1385. X    {
  1386. X      if (foundsock[s].mode == -1)
  1387. X        {
  1388. X              strcpy(SockNamePtr, foundsock[s].name);
  1389. X          debug1("wiping '%d'\n", SockPath);
  1390. X          if (unlink(SockPath) == 0)
  1391. X            {
  1392. X          foundsock[s].mode = -2;
  1393. X              wipecount++;
  1394. X        }
  1395. X        }
  1396. X    }
  1397. X    }
  1398. X  for (s = 0; s < foundsockcount; s++)
  1399. X    if ((foundsock[s].mode) == (dflag ? 0700 : 0600))
  1400. X      {
  1401. X    found++;
  1402. X    lasts = s;
  1403. X      }
  1404. X  if (quietflag && (lsflag || (found != 1 && rflag !=2)))
  1405. X    eexit(10+found);
  1406. X  debug2("attach: found=%d, foundsockcount=%d\n", found, foundsockcount);
  1407. X  if (found == 1 && lsflag == 0)
  1408. X    {
  1409. X      if ((lasts = MakeClientSocket(0, foundsock[lasts].name)) == -1)
  1410. X        found = 0;
  1411. X    }
  1412. X  else if (!quietflag && foundsockcount > 0)
  1413. X    {
  1414. X      switch (found)
  1415. X        {
  1416. X        case 0:
  1417. X          if (lsflag)
  1418. X        {
  1419. X#ifdef NETHACK
  1420. X              if (nethackflag)
  1421. X            printf("Your inventory:\n");
  1422. X          else
  1423. X#endif
  1424. X          printf((foundsockcount>1) ? "There are screens on:\n" : "There is a screen on:\n");
  1425. X        }
  1426. X          else
  1427. X        {
  1428. X#ifdef NETHACK
  1429. X              if (nethackflag)
  1430. X            printf("Nothing fitting exists in the game:\n");
  1431. X          else
  1432. X#endif
  1433. X          printf((foundsockcount>1) ? "There are screens on:\n" : "There is a screen on:\n");
  1434. X        }
  1435. X          break;
  1436. X        case 1:
  1437. X#ifdef NETHACK
  1438. X          if (nethackflag)
  1439. X            printf((foundsockcount>1) ? "Prove thyself worthy or perish:\n" : "You see here a good looking screen:\n");
  1440. X          else
  1441. X#endif
  1442. X          printf((foundsockcount>1) ? "There are several screens on:\n" : "There is a possible screen on:\n");
  1443. X          break;
  1444. X        default:
  1445. X#ifdef NETHACK
  1446. X          if (nethackflag)
  1447. X            printf((foundsockcount>1) ? "You may whish for a screen, what do you want?\n" : "You see here a screen:\n");
  1448. X          else
  1449. X#endif
  1450. X          printf((foundsockcount>1) ? "There are several screens on:\n" : "There is a screen on:\n");
  1451. X          break;
  1452. X        }
  1453. X      for (s = 0; s < foundsockcount; s++)
  1454. X    {
  1455. X      switch (foundsock[s].mode)
  1456. X        {
  1457. X        case 0700:
  1458. X          printf("\t%s\t(Attached)\n", foundsock[s].name);
  1459. X          break;
  1460. X        case 0600:
  1461. X          printf("\t%s\t(Detached)\n", foundsock[s].name);
  1462. X          break;
  1463. X        case -1:
  1464. X#if defined(__STDC__)
  1465. X          printf("\t%s\t(Dead \?\?\?)\n", foundsock[s].name);
  1466. X#else
  1467. X          printf("\t%s\t(Dead ???)\n", foundsock[s].name);
  1468. X#endif
  1469. X          break;
  1470. X        case -2:
  1471. X          printf("\t%s\t(Removed)\n", foundsock[s].name);
  1472. X          break;
  1473. X        default:
  1474. X          printf("\t%s\t(Wrong mode)\n", foundsock[s].name);
  1475. X          break;
  1476. X        }
  1477. X    }
  1478. X    }
  1479. X  if (deadcount && !quietflag)
  1480. X    {
  1481. X      if (wipeflag)
  1482. X        {
  1483. X#ifdef NETHACK
  1484. X          if (nethackflag)
  1485. X            printf("You hear%s distant explosion%s.\n",
  1486. X           (deadcount > 1)?"":" a", (deadcount > 1)?"s":"");
  1487. X          else
  1488. X#endif
  1489. X          printf("%d Socket%s wiped out.\n", deadcount, (deadcount > 1)?"s":"");
  1490. X    }
  1491. X      else
  1492. X    {
  1493. X#ifdef NETHACK
  1494. X          if (nethackflag)
  1495. X            printf("The dead screen%s touch%s you. Try 'screen -wipe'.\n",
  1496. X           (deadcount > 1)?"s":"", (deadcount >1)?"":"es");
  1497. X          else
  1498. X#endif
  1499. X          printf("Remove dead Sockets with 'screen -wipe'.\n");
  1500. X    }
  1501. X    }
  1502. X
  1503. X  for (s = 0; s < foundsockcount; s++)
  1504. X    Free(foundsock[s].name);
  1505. X  if (found == 1 && fdp)
  1506. X    *fdp = lasts;
  1507. X  if (fdp)
  1508. X    return found;
  1509. X  SockName = NULL;
  1510. X  return foundsockcount - wipecount;
  1511. X}
  1512. X
  1513. int
  1514. GetSockName()
  1515. X{
  1516. X  register int client;
  1517. X  static char buf[2 * MAXSTR];
  1518. X
  1519. X  if (!mflag && (SockName = getenv("STY")) != 0 && *SockName != '\0')
  1520. X    {
  1521. X      client = 1;
  1522. X      setuid(real_uid);
  1523. X      setgid(real_gid);
  1524. X    }
  1525. X  else
  1526. X    {
  1527. X      sprintf(buf, "%s.%s", HostName, Filename(GetTtyName()));
  1528. X      SockName = buf;
  1529. X      client = 0;
  1530. X    }
  1531. X  return client;
  1532. X}
  1533. X
  1534. X#ifdef NAMEDPIPE
  1535. X
  1536. int
  1537. MakeServerSocket()
  1538. X{
  1539. X  register int s;
  1540. X  struct stat st;
  1541. X
  1542. X  strcpy(SockNamePtr, SockName);
  1543. X
  1544. X  if ((s = open(SockPath, O_WRONLY | O_NDELAY)) >= 0)
  1545. X    {
  1546. X      debug("huii, my fifo already exists??\n");
  1547. X      if (quietflag)
  1548. X    {
  1549. X      Kill(AttacherPid, SIG_BYE);
  1550. X      eexit(11);
  1551. X    }
  1552. X      printf("There is already a screen running on %s.\n",
  1553. X         Filename(SockPath));
  1554. X      if (stat(SockPath, &st) == -1)
  1555. X    Msg(errno, "stat");
  1556. X      if (st.st_uid != real_uid)
  1557. X    Msg(0, "Unfortunatelly you are not its owner.");
  1558. X      if ((st.st_mode & 0700) == 0600)
  1559. X    Msg(0, "To resume it, use \"screen -r\"");
  1560. X      else
  1561. X    Msg(0, "It is not detached.");
  1562. X      /* NOTREACHED */
  1563. X    }
  1564. X  (void) unlink(SockPath);
  1565. X  if (UserContext() > 0)
  1566. X    {
  1567. X      if (mknod(SockPath, S_IFIFO | S_IEXEC | S_IWRITE | S_IREAD, 0))
  1568. X    UserReturn(0);
  1569. X      UserReturn(1);
  1570. X    }
  1571. X  if (UserStatus() <= 0)
  1572. X    Msg(0, "mknod fifo %s failed", SockPath);
  1573. X  /*
  1574. X   * MUST be RDWR because otherwise we will get EOF's if
  1575. X   * nobody has opened the pipe for writing
  1576. X   */
  1577. X  if ((s = secopen(SockPath, O_RDWR | O_NDELAY, 0)) < 0)
  1578. X    Msg(errno, "open fifo %s", SockPath);
  1579. X  return s;
  1580. X}
  1581. X
  1582. X
  1583. int
  1584. MakeClientSocket(err, name)
  1585. int err;
  1586. char *name;
  1587. X{
  1588. X  register int s = 0;
  1589. X
  1590. X  strcpy(SockNamePtr, name);
  1591. X
  1592. X  
  1593. X  if ((s = secopen(SockPath, O_WRONLY | O_NDELAY, 0)) >= 0)
  1594. X    {
  1595. X      (void) fcntl(s, F_SETFL, 0);
  1596. X      return s;
  1597. X    }
  1598. X  if (err)
  1599. X    {
  1600. X      Msg(errno, "open: %s (but continuing...)", SockPath);
  1601. X      debug1("MakeClientSocket() open %s failed\n", SockPath);
  1602. X    }
  1603. X  else
  1604. X    {
  1605. X      debug1("MakeClientSocket() open %s failed\n", SockPath);
  1606. X    }
  1607. X  return -1;
  1608. X}
  1609. X
  1610. X#else    /* NAMEDPIPE */
  1611. X
  1612. int
  1613. MakeServerSocket()
  1614. X{
  1615. X  register int s;
  1616. X  struct sockaddr_un a;
  1617. X  struct stat st;
  1618. X
  1619. X  if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  1620. X    Msg(errno, "socket");
  1621. X  a.sun_family = AF_UNIX;
  1622. X  strcpy(SockNamePtr, SockName);
  1623. X  strcpy(a.sun_path, SockPath);
  1624. X  if (connect(s, (struct sockaddr *) & a, strlen(SockPath) + 2) != -1)
  1625. X    {
  1626. X      debug("oooooh! socket already is alive!\n");
  1627. X      if (quietflag)
  1628. X    { 
  1629. X      Kill(AttacherPid, SIG_BYE);
  1630. X      /* 
  1631. X       * oh, well. nobody receives that return code. papa 
  1632. X       * dies by signal.
  1633. X       */
  1634. X      eexit(11);
  1635. X    }
  1636. X      printf("There is already a screen running on %s.\n",
  1637. X         Filename(SockPath));
  1638. X      if (stat(SockPath, &st) == -1)
  1639. X    Msg(errno, "stat");
  1640. X      if (st.st_uid != real_uid)
  1641. X    Msg(0, "Unfortunatelly you are not its owner.");
  1642. X      if ((st.st_mode & 0700) == 0600)
  1643. X    Msg(0, "To resume it, use \"screen -r\"");
  1644. X      else
  1645. X    Msg(0, "It is not detached.");
  1646. X      /* NOTREACHED */
  1647. X    }
  1648. X  (void) unlink(SockPath);
  1649. X#ifndef NOREUID
  1650. X  setreuid(eff_uid, real_uid);
  1651. X  setregid(eff_gid, real_gid);
  1652. X#endif
  1653. X  if (bind(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1)
  1654. X    Msg(errno, "bind");
  1655. X  (void) chmod(SockPath, /* S_IFSOCK | */ 0700);
  1656. X#ifdef NOREUID
  1657. X  chown(SockPath, real_uid, real_gid);
  1658. X#else
  1659. X  setreuid(real_uid, eff_uid);
  1660. X  setregid(real_gid, eff_gid);
  1661. X#endif
  1662. X  if (listen(s, 5) == -1)
  1663. X    Msg(errno, "listen");
  1664. X#ifdef F_SETOWN
  1665. X  fcntl(s, F_SETOWN, getpid());
  1666. X  debug1("Serversocket owned by %d\n",fcntl(s, F_GETOWN, 0));
  1667. X#endif /* F_SETOWN */
  1668. X  return s;
  1669. X}
  1670. X
  1671. int
  1672. MakeClientSocket(err, name)
  1673. int err;
  1674. char *name;
  1675. X{
  1676. X  register int s;
  1677. X  struct sockaddr_un a;
  1678. X
  1679. X  if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  1680. X    Msg(errno, "socket");
  1681. X  a.sun_family = AF_UNIX;
  1682. X  strcpy(SockNamePtr, name);
  1683. X  strcpy(a.sun_path, SockPath);
  1684. X#ifndef NOREUID
  1685. X  setreuid(eff_uid, real_uid);
  1686. X  setregid(eff_gid, real_gid);
  1687. X#else
  1688. X  if (access(SockPath, W_OK))
  1689. X    {
  1690. X      if (err)
  1691. X    Msg(errno, "%s", SockPath);
  1692. X      else
  1693. X    debug2("MakeClientSocket: access(%s): %d.\n", SockPath, errno);
  1694. X      close(s);
  1695. X      return -1;
  1696. X    }
  1697. X#endif
  1698. X  if (connect(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1)
  1699. X    {
  1700. X      if (err)
  1701. X    Msg(errno, "%s: connect", SockPath);
  1702. X      else
  1703. X    debug("MakeClientSocket: connect failed.\n");
  1704. X      close(s);
  1705. X      s = -1;
  1706. X    }
  1707. X#ifndef NOREUID
  1708. X  setreuid(real_uid, eff_uid);
  1709. X  setregid(real_gid, eff_gid);
  1710. X#endif
  1711. X  return s;
  1712. X}
  1713. X#endif
  1714. X
  1715. X
  1716. void
  1717. SendCreateMsg(s, ac, av, aflag, flowflag, lflag, histheight, sterm)
  1718. int s, ac, aflag, flowflag, lflag, histheight;
  1719. char **av;
  1720. char *sterm;
  1721. X{
  1722. X  struct msg m;
  1723. X  register char *p;
  1724. X  register int len, n;
  1725. X
  1726. X  debug1("SendCreateMsg() to '%s'\n", SockPath);
  1727. X  m.type = MSG_CREATE;
  1728. X  p = m.m.create.line;
  1729. X  for (n = 0; ac > 0 && n < MAXARGS - 1; ++av, --ac, ++n)
  1730. X    {
  1731. X      len = strlen(*av) + 1;
  1732. X      if (p + len >= m.m.create.line + MAXPATH - 1)
  1733. X    break;
  1734. X      strcpy(p, *av);
  1735. X      p += len;
  1736. X    }
  1737. X  if (!ac && *av && p + strlen(*av) + 1 < m.m.create.line + MAXPATH)
  1738. X    strcpy(p, *av);
  1739. X  else
  1740. X    *p = '\0';
  1741. X  m.m.create.nargs = n;
  1742. X  m.m.create.aflag = aflag;
  1743. X  m.m.create.flowflag = flowflag;
  1744. X  m.m.create.lflag = lflag;
  1745. X  m.m.create.hheight = histheight;
  1746. X#ifdef SYSV
  1747. X  if (getcwd(m.m.create.dir, sizeof(m.m.create.dir)) == 0)
  1748. X#else
  1749. X    if (getwd(m.m.create.dir) == 0)
  1750. X#endif
  1751. X      Msg(0, "%s", m.m.create.dir);
  1752. X  strncpy(m.m.create.screenterm, sterm, 19);
  1753. X  m.m.create.screenterm[19] = '\0';
  1754. X  debug1("SendCreateMsg writing '%s'\n", m.m.create.line);
  1755. X  if (write(s, (char *) &m, sizeof m) != sizeof m)
  1756. X    Msg(errno, "write");
  1757. X}
  1758. X
  1759. void
  1760. X#ifdef USEVARARGS
  1761. X/*VARARGS1*/
  1762. X# if defined(__STDC__)
  1763. SendErrorMsg(char *fmt, ...)
  1764. X# else
  1765. SendErrorMsg(fmt, va_alist)
  1766. char *fmt;
  1767. va_dcl
  1768. X#endif
  1769. X{ /* } */
  1770. X  static va_list ap = 0;
  1771. X#else
  1772. X/*VARARGS1*/
  1773. SendErrorMsg(fmt, p1, p2, p3, p4, p5, p6)
  1774. char *fmt;
  1775. unsigned long p1, p2, p3, p4, p5, p6;
  1776. X{
  1777. X#endif
  1778. X  register int s;
  1779. X  struct msg m;
  1780. X
  1781. X  s = MakeClientSocket(1, SockName);
  1782. X  debug1("SendErrorMsg() to '%s'\n", SockPath);
  1783. X  m.type = MSG_ERROR;
  1784. X#ifdef USEVARARGS
  1785. X# if defined(__STDC__)
  1786. X  va_start(ap, fmt);
  1787. X# else
  1788. X  va_start(ap);
  1789. X# endif
  1790. X  (void) vsprintf(m.m.message, fmt, ap);
  1791. X  va_end(ap);
  1792. X#else
  1793. X  sprintf(m.m.message, fmt, p1, p2, p3, p4, p5, p6);
  1794. X#endif
  1795. X  debug1("SendErrorMsg writing '%s'\n", m.m.message);
  1796. X  (void) write(s, (char *) &m, sizeof m);
  1797. X  close(s);
  1798. X  sleep(2);
  1799. X}
  1800. X
  1801. X#ifdef PASSWORD
  1802. static int CheckPasswd(pwd, pid, tty)
  1803. int pid;
  1804. char *pwd, *tty;
  1805. X{
  1806. X  if (CheckPassword && 
  1807. X      strcmp(crypt(pwd, ((unsigned)strlen(Password) > 1) ? Password : "JW"),
  1808. X         Password))
  1809. X    {
  1810. X      if (*pwd)
  1811. X    {
  1812. X#ifdef NETHACK
  1813. X          if (nethackflag)
  1814. X        Msg(0, "'%s' tries to explode in the sky, but fails. (%s)", tty, pwd);
  1815. X          else
  1816. X#endif
  1817. X      Msg(0, "Illegal reattach attempt from terminal %s, \"%s\"", tty, pwd);
  1818. X    }
  1819. X      debug1("CheckPass() wrong password kill(%d, SIG_PW_FAIL)\n", pid);
  1820. X      Kill(pid, SIG_PW_FAIL);
  1821. X      return 0;
  1822. X    }
  1823. X  debug1("CheckPass() from %d happy\n", pid);
  1824. X  Kill(pid, SIG_PW_OK);
  1825. X  return 1;
  1826. X}
  1827. X#endif    /* PASSWORD */
  1828. X
  1829. static void ExecCreate(mp)
  1830. struct msg *mp;
  1831. X{
  1832. X  char *args[MAXARGS];
  1833. X  register int n;
  1834. X  register char **pp = args, *p = mp->m.create.line;
  1835. X
  1836. X  for (n = mp->m.create.nargs; n > 0; --n)
  1837. X    {
  1838. X      *pp++ = p;
  1839. X      p += strlen(p) + 1;
  1840. X    }
  1841. X  *pp = 0;
  1842. X  if (!*p)
  1843. X    p = 0;
  1844. X  MakeWindow(p, args, mp->m.create.aflag, mp->m.create.flowflag,
  1845. X              0, mp->m.create.dir, mp->m.create.lflag,
  1846. X              mp->m.create.hheight, mp->m.create.screenterm);
  1847. X}
  1848. X
  1849. void
  1850. ReceiveMsg(s)
  1851. int s;
  1852. X{
  1853. X  int left, len, i;
  1854. X  struct msg m;
  1855. X  char *p;
  1856. X  char buf[20];
  1857. X#ifdef NAMEDPIPE
  1858. X  /*
  1859. X   * we may be called if there are no pending messages, so we will have to
  1860. X   * block on first read.
  1861. X   */
  1862. X  debug("Ha, there was someone knocking on my fifo??\n");
  1863. X  if (fcntl(s, F_SETFL, 0) == -1)
  1864. X    {
  1865. X      Msg(errno, "fcntl no O_NDELAY");
  1866. X      exit(1);
  1867. X    }
  1868. X  p = (char *) &m;
  1869. X  left = sizeof(m);
  1870. X  while (left > 0 && (len = read(s, p, left)) > 0)
  1871. X    {
  1872. X      /*        if (p == (char *)&m)
  1873. X       *        {    if (fcntl(s,F_SETFL,O_NDELAY) == -1)
  1874. X       *            {    Msg(errno, "fcntl O_NDELAY !");
  1875. X       *                return;
  1876. X       *            }
  1877. X       *        }
  1878. X       */
  1879. X      p += len;
  1880. X      left -= len;
  1881. X    }
  1882. X# ifdef DEBUG
  1883. X  if (len == 0)
  1884. X    debug("ReceiveMsg: Yucc! Got an EOF !!\n");
  1885. X# endif
  1886. X#else
  1887. X  register int ns;
  1888. X  struct sockaddr_un a;
  1889. X
  1890. X  len = sizeof(struct sockaddr_un);
  1891. X  debug("Ha, there was someone knocking on my socket??\n");
  1892. X  if ((ns = accept(s, (struct sockaddr *) & a, &len)) == -1)
  1893. X    {
  1894. X      Msg(errno, "accept");
  1895. X      return;
  1896. X    }
  1897. X  p = (char *) &m;
  1898. X  left = sizeof m;
  1899. X  while (left > 0 && (len = read(ns, p, left)) > 0)
  1900. X    {
  1901. X      p += len;
  1902. X      left -= len;
  1903. X    }
  1904. X  close(ns);
  1905. X#endif                /* NAMEDPIPE */
  1906. X
  1907. X  if (len == -1)
  1908. X    Msg(errno, "read");
  1909. X  if (left > 0)
  1910. X    return;
  1911. X  debug1("RecMsg: type %d !, ", m.type);
  1912. X  switch (m.type)
  1913. X    {
  1914. X    case MSG_WINCH:
  1915. X      /* Already processed in screen.c */
  1916. X#ifdef notdef
  1917. X      CheckScreenSize(1); /* Change fore */
  1918. X#endif
  1919. X      break;
  1920. X    case MSG_CREATE:
  1921. X      if (!Detached)
  1922. X    ExecCreate(&m);
  1923. X      break;
  1924. X    case MSG_CONT:
  1925. X      debug3("RecMsg: apid=%d,was %d, Detached=%d\n", m.m.attach.apid, AttacherPid, Detached);
  1926. X
  1927. X#ifdef SECURE_MSG_CONT
  1928. X      if (m.m.attach.apid != AttacherPid || !Detached)
  1929. X    /*
  1930. X     * now we realize, that there is something strange happening.
  1931. X     * First, there was some idiot who said "CONT" and thought
  1932. X     * "ATTACH". This is, when we have (AttacherPid == 0). Harmless.
  1933. X     * Let him in. Second, we are waiting for a certain AttacherPid,
  1934. X     * and not for "any" attacher. This is when (AttacherPid != 0).
  1935. X     * But Darwin's rule says "survival of the fittest", thus: Look
  1936. X     * weather "our" AttacherPid is still alive and well, and let the
  1937. X     * new one only in, if the old Attacher has been killed. jw.
  1938. X     */
  1939. X    if (AttacherPid != 0 && kill(AttacherPid, 0) == 0)
  1940. X      break;        /* Intruder Alert */
  1941. X    else
  1942. X#endif                /* SECURE_MSG_CONT */
  1943. X      AttacherPid = 0;    /* we dont want to kill ourselves
  1944. X                 * later. jw. */
  1945. X      /* FALLTHROUGH */
  1946. X    case MSG_ATTACH:
  1947. X      if (CheckPid(m.m.attach.apid))
  1948. X    {
  1949. X      debug1("Attach attempt with bad pid(%d)\n", m.m.attach.apid);
  1950. X      Msg(0, "Attach attempt with bad pid(%d) !", m.m.attach.apid);
  1951. X          break;
  1952. X    }
  1953. X#ifdef PASSWORD
  1954. X      if (!CheckPasswd(m.m.attach.password, m.m.attach.apid, m.m.attach.tty))
  1955. X    {
  1956. X      debug3("RcvMsg:Checkpass(%s,%d,%s) failed\n",
  1957. X         m.m.attach.password, m.m.attach.apid, m.m.attach.tty);
  1958. X      break;
  1959. X    }
  1960. X#endif                /* PASSWORD */
  1961. X      if (!Detached)
  1962. X    {
  1963. X      debug("RecMsg: hey, why you disturb, we are not detached. hangup!\n");
  1964. X      Kill(m.m.attach.apid, SIG_BYE);
  1965. X      Msg(0, "Attach msg ignored: We are not detached.");
  1966. X      break;
  1967. X    }
  1968. X      if ((i = secopen(m.m.attach.tty, O_RDWR | O_NDELAY, 0)) < 0)
  1969. X    {
  1970. X      debug1("ALERT: Cannot open %s!\n", m.m.attach.tty);
  1971. X#ifdef NETHACK
  1972. X          if (nethackflag)
  1973. X        Msg(errno, "You can't open (%s). Perhaps there's a Monster behind it."
  1974. X          ,m.m.attach.tty);
  1975. X          else
  1976. X#endif
  1977. X      Msg(errno, "Attach: Could not open %s", m.m.attach.tty);
  1978. X      Kill(m.m.attach.apid, SIG_BYE);
  1979. X      break;
  1980. X    }
  1981. X      errno = 0;
  1982. X      if (i)
  1983. X    {
  1984. X      debug("PANIC: open did not return fd 0!\n");
  1985. X      close(0);
  1986. X      dup(i);
  1987. X      close(i);
  1988. X      close(1);
  1989. X      close(2);
  1990. X    }
  1991. X      debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", m.m.attach.apid, m.m.attach.tty);
  1992. X
  1993. X#ifdef hpux_and_it_still_does_not_work
  1994. X      {
  1995. X    int pgrp, zero = 0;
  1996. X
  1997. X    if (ioctl(0, TIOCGPGRP, &pgrp) == -1)
  1998. X      debug1("tcgetpgrp: %d\n", errno);    /* save old pgrp from
  1999. X                           tty */
  2000. X
  2001. X    if (ioctl(0, TIOCSPGRP, &zero) == -1)
  2002. X      debug1("tcsetpgrp: %d\n", errno);    /* detach tty from proc
  2003. X                           grp */
  2004. X#ifdef hpux
  2005. X    setpgrp();
  2006. X#else
  2007. X    if (setpgrp(0, getpid()) == -1)
  2008. X      debug1("setpgrp: %d\n", errno);    /* make me process group
  2009. X                                 leader */
  2010. X#endif
  2011. X
  2012. X    close(0);    /* reopen tty, now we should get it as our
  2013. X             * tty */
  2014. X    (void) secopen(m.m.attach.tty, O_RDWR | O_NDELAY, 0);    /* */
  2015. X
  2016. X#ifdef hpux
  2017. X    setpgrp2(0, pgrp);
  2018. X#else
  2019. X    setpgrp(0, pgrp);
  2020. X#endif
  2021. X    ioctl(0, TIOCSPGRP, &pgrp);
  2022. X      }
  2023. X#endif  /* hpux_and_it_still_does_not_work */
  2024. X
  2025. X      (void) dup(0);
  2026. X      (void) dup(0);
  2027. X      GetTTY(0, &OldMode);
  2028. X      SetMode(&OldMode, &NewMode);
  2029. X      SetTTY(0, &NewMode);
  2030. X#if !defined(POSIX) && defined(BSDJOBS)
  2031. X      if ((DevTty = open("/dev/tty", O_RDWR | O_NDELAY)) == -1)
  2032. X    {
  2033. X      debug1("DevTty not opened: %d.\n", errno);
  2034. X      Msg(errno, "/dev/tty");
  2035. X    }
  2036. X#endif
  2037. X      signal(SIGHUP, SigHup);
  2038. X#ifdef BSDJOBS
  2039. X      if (Suspended && m.type == MSG_ATTACH)
  2040. X    if (kill(AttacherPid, SIG_BYE) == 0)
  2041. X      kill(AttacherPid, SIGCONT);
  2042. X#endif
  2043. X
  2044. X      AttacherPid = m.m.attach.apid;
  2045. X#ifdef UTMPOK
  2046. X      /*
  2047. X       * we set the Utmp slots again, if we were detached normally
  2048. X       * and if we were detached by ^Z.
  2049. X       */
  2050. X      ReInitUtmp();
  2051. X      for (i = WinList; i != -1; i = wtab[i]->WinLink)
  2052. X    if (wtab[i]->slot != (slot_t) -1)
  2053. X      SetUtmp(wtab[i], i);
  2054. X#endif
  2055. X      (void) chmod(SockPath, /* S_IFSOCK | */ 0700);
  2056. X      Detached = 0;
  2057. X#ifdef BSDJOBS
  2058. X      Suspended = 0;
  2059. X#endif
  2060. X      /*
  2061. X       * we like to have always the valid termcap, even if we are
  2062. X       * reattached from a different tty type. thus attacher had to
  2063. X       * tell us, what TERM we have. The attacher has correct env
  2064. X       * setting. we (the backend may be wrong).
  2065. X       */
  2066. X      if (*m.m.attach.envterm)
  2067. X    {
  2068. X#if defined(pyr) || defined(xelos) || defined(sequent)
  2069. X      /*
  2070. X       * Kludge for systems with braindamaged termcap routines,
  2071. X       * which evaluate $TERMCAP, regardless weather it describes
  2072. X       * the correct terminal type or not.
  2073. X       */
  2074. X      if (strcmp(getenv("TERM"), m.m.attach.envterm + 5))
  2075. X        {
  2076. X          debug("a different terminal, so unsetenv(TERMCAP)");
  2077. X          unsetenv("TERMCAP");
  2078. X        }
  2079. X#endif
  2080. X    
  2081. X#if !defined(sequent) && !defined(MIPS)
  2082. X      putenv(m.m.attach.envterm);
  2083. X#else
  2084. X      setenv("TERM", m.m.attach.envterm + 5, 1);
  2085. X#endif
  2086. X    }
  2087. X#if !defined(sequent) && !defined(MIPS)
  2088. X      sprintf(buf, "LINES=%d", m.m.attach.lines);
  2089. X      if (m.m.attach.lines > 0 || getenv("LINES"))
  2090. X        putenv(buf);
  2091. X      sprintf(buf, "COLUMNS=%d", m.m.attach.columns);
  2092. X      if (m.m.attach.columns > 0 || getenv("COLUMNS"))
  2093. X        putenv(buf);
  2094. X#else
  2095. X      sprintf(buf, "%d", m.m.attach.lines);
  2096. X      if (m.m.attach.lines > 0 || getenv("LINES"))
  2097. X        setenv("LINES", buf);
  2098. X      sprintf(buf, "%d", m.m.attach.columns);
  2099. X      if (m.m.attach.columns > 0 || getenv("COLUMNS"))
  2100. X        setenv("COLUMNS", buf);
  2101. X#endif
  2102. X      
  2103. X      /*
  2104. X       * We reboot our Terminal Emulator. Forget all we knew about
  2105. X       * the old terminal, reread the termcap entries in .screenrc
  2106. X       * (and nothing more from .screenrc is read. Mainly because
  2107. X       * I did not check, weather a full reinit is save. jw) 
  2108. X       * and /etc/screenrc, and initialise anew.
  2109. X       */
  2110. X      if (extra_outcap)
  2111. X    Free(extra_outcap);
  2112. X      if (extra_incap)
  2113. X    Free(extra_incap);
  2114. X#ifdef ETCSCREENRC
  2115. X      if ((p = getenv("SYSSCREENRC")) == NULL)
  2116. X    StartRc(ETCSCREENRC);
  2117. X      else
  2118. X    StartRc(p);
  2119. X#endif
  2120. X      StartRc(RcFileName);
  2121. X      InitTermcap();
  2122. X      InitTerm(m.m.attach.adaptflag);
  2123. X      fore->active = 1;
  2124. X      Activate();
  2125. X      debug("activated...\n");
  2126. X      break;
  2127. X    case MSG_ERROR:
  2128. X      Msg(0, "%s", m.m.message);
  2129. X      break;
  2130. X    case MSG_HANGUP:
  2131. X#ifdef REMOTE_DETACH
  2132. X    case MSG_DETACH:
  2133. X# ifdef POW_DETACH
  2134. X    case MSG_POW_DETACH:
  2135. X# endif                /* POW_DETACH */
  2136. X#endif
  2137. X      if (CheckPid(m.m.detach.dpid))
  2138. X    {
  2139. X      Msg(0, "Detach/Hup attempt with bad pid !!");
  2140. X          break;
  2141. X    }
  2142. X#ifdef PASSWORD
  2143. X      if (!CheckPasswd(m.m.detach.password, m.m.detach.dpid, m.m.detach.tty))
  2144. X    return;
  2145. X#endif                /* PASSWORD */
  2146. X#ifdef REMOTE_DETACH
  2147. X# ifdef POW_DETACH
  2148. X      if (m.type == MSG_POW_DETACH)
  2149. X    Detach(D_REMOTE_POWER);
  2150. X      else
  2151. X# endif                /* POW_DETACH */
  2152. X      if (m.type == MSG_DETACH)
  2153. X    Detach(D_REMOTE);
  2154. X      else
  2155. X#endif
  2156. X      SigHup(SIGARG);
  2157. X      break;
  2158. X    default:
  2159. X      Msg(0, "Invalid message (type %d).", m.type);
  2160. X    }
  2161. X}
  2162. X
  2163. X#if defined(_SEQUENT_) && !defined(NAMEDPIPE)
  2164. X#undef connect
  2165. X
  2166. sconnect(s,sapp,len)
  2167. int s,len;
  2168. struct sockaddr *sapp;
  2169. X{
  2170. X  register struct sockaddr_un *sap;
  2171. X  struct stat st;
  2172. X  int x;
  2173. X
  2174. X  sap=(struct sockaddr_un *)sapp;
  2175. X  if (stat(sap->sun_path,&st))
  2176. X    return(-1);
  2177. X  chmod(sap->sun_path,0);
  2178. X  x=connect(s, (struct sockaddr *) sap, len);
  2179. X  chmod(sap->sun_path,st.st_mode);
  2180. X  return(x);
  2181. X}
  2182. X#endif
  2183. END_OF_FILE
  2184. if test 25596 -ne `wc -c <'socket.c'`; then
  2185.     echo shar: \"'socket.c'\" unpacked with wrong size!
  2186. fi
  2187. # end of 'socket.c'
  2188. fi
  2189. echo shar: End of archive 4 \(of 8\).
  2190. cp /dev/null ark4isdone
  2191. MISSING=""
  2192. for I in 1 2 3 4 5 6 7 8 ; do
  2193.     if test ! -f ark${I}isdone ; then
  2194.     MISSING="${MISSING} ${I}"
  2195.     fi
  2196. done
  2197. if test "${MISSING}" = "" ; then
  2198.     echo You have unpacked all 8 archives.
  2199.     rm -f ark[1-9]isdone
  2200. else
  2201.     echo You still need to unpack the following archives:
  2202.     echo "        " ${MISSING}
  2203. fi
  2204. ##  End of shell archive.
  2205. exit 0
  2206.